/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#include "MkHttpMediaSession.h"
#include "MkFlv/MkFlvMuxer.h"
#include "MkMedia/MkMediaSource.h"
#include "MkUtil/MkLog.h"


CMkWsFlvConsume::CMkWsFlvConsume()
    : CMkMediaConsume(MkMediaConsumeWsFlv)
{

}

Uint32 CMkWsFlvConsume::ConsumeEsPacket(CMkMediaSource* pSource, const MkEsPacket& EsPacket, Uint8* pBuf, Uint32 nLen)
{
    Uint32 nEsUsed = 0;
    Uint32 nUsed = 0;
    CMkBufferList EsBufferList;
    CMkFlvMuxer::PacketEsPacket(pSource->GetVideoParam(), pSource->GetAudioParam(), EsPacket, pBuf, nLen, nEsUsed, EsBufferList);

    CMkHttpMediaSession* pFlvConsumer = nullptr;
    MkMap<MkString, CMkMediaConsumer*>::iterator it = GetMapConsumer().begin();
    for (; it != GetMapConsumer().end(); it++) {
        pFlvConsumer = dynamic_cast<CMkHttpMediaSession*>(it->second);
        if (!pFlvConsumer) {
            continue;
        }
        if (pFlvConsumer->IsFirstSend()) {
            CMkBufferList BufferList;
            BufferList.Clear();
            CMkFlvMuxer::PacketHeader(pSource->GetVideoParam(), pSource->GetAudioParam(), pSource->m_FileSize, pSource->m_Duration, pBuf + nEsUsed, nLen - nEsUsed, BufferList);

            pFlvConsumer->SendWebSocketBinary(BufferList);
            MkVector<MkCacheEsPacket>::const_iterator itCache = pSource->GetCacheEsPacket().begin();
            for (; itCache != pSource->GetCacheEsPacket().end(); itCache++) {
                MkEsPacket TmpEsPacket;
                CMkMediaUtil::ReadCachePacket(*itCache, TmpEsPacket);
                BufferList.Clear();

                CMkFlvMuxer::PacketEsPacket(pSource->GetVideoParam(), pSource->GetAudioParam(), TmpEsPacket, pBuf + nEsUsed, nLen - nEsUsed, nUsed, BufferList);
                pFlvConsumer->SendWebSocketBinary(BufferList);
            }
            BufferList.Clear();
            CMkFlvMuxer::PacketEsPacket(pSource->GetVideoParam(), pSource->GetAudioParam(), EsPacket, pBuf + nEsUsed, nLen - nEsUsed, nUsed, BufferList);
            pFlvConsumer->SendWebSocketBinary(BufferList);
            pFlvConsumer->SetFirstSend(FALSE);
        }
        pFlvConsumer->SendFlvStream(EsPacket, EsBufferList);
    }
    return NoneError;
}

CMkHttpMediaSession::CMkHttpMediaSession(CMkEvent *pEvent, CMkTimer* pTimer, CMkHttpServer* parent)
    : CMkHttpSession(pEvent, pTimer, parent)
    , CMkMediaConsumer(MkMediaConsumeWsFlv)
{

}

Uint32 CMkHttpMediaSession::SendFlvStream(const MkEsPacket& EsPacket, const CMkBufferList& BufferList)
{
    AddSendBytes(BufferList.GetTatolLen());
    Uint32 ErrorCode = NoneError;
    //has un send buffer big than half 1MB
    if ((GetUnSendBufferLength() > LenHalfM && EsPacket.bKeyPacket) || !m_ListCacheStream.empty()) {
        MkList<MkCacheStreamPacket>::iterator it;
        if (EsPacket.bKeyPacket) {
            it = m_ListCacheStream.begin();
            for (; it != m_ListCacheStream.end(); it++) {
                it->CacheBufferList.Clear();
            }
            m_ListCacheStream.clear();
        }
        MkCacheStreamPacket CacheStreamPacket;
        CMkMediaUtil::WriteCacheStream(EsPacket, BufferList, CacheStreamPacket);
        m_ListCacheStream.push_back(CacheStreamPacket);
        //send all un send packet
        if (GetUnSendBufferLength() < Len20K) {
            it = m_ListCacheStream.begin();
            for (; it != m_ListCacheStream.end(); it++) {
                CMkBufferList SendList;
                it->CacheBufferList.GetBufferList(SendList);
                ErrorCode = SendWebSocketBinary(SendList);
                it->CacheBufferList.Clear();
            }
            m_ListCacheStream.clear();
        }
    } else {
        ErrorCode = SendWebSocketBinary(BufferList);
    }
    return ErrorCode;
}

void CMkHttpMediaSession::Release()
{
    Close();
}

CMkHttpMediaSession::~CMkHttpMediaSession()
{
    //MkErrorLog("delete media session:%p\n", this);
    MkList<MkCacheStreamPacket>::iterator it = m_ListCacheStream.begin();
    for (; it != m_ListCacheStream.end(); it++) {
        it->CacheBufferList.Clear();
    }
    m_ListCacheStream.clear();
}

CMkWsFlvConsume::~CMkWsFlvConsume()
{

}
